/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
var app = {
    canvas:null,
    ctx:null,
    bufferCanvas:null,
    bufferCtx:null,
    rowNum:17,
    columnNum:31,
    gridSize:null,
    width:null,
    height:null,
    pos:{x:0,y:0},
    speed:{x:0,y:0},
    watchID:null,
    fps:4,
    meSpirit:null,
    maze:null,
    map:null,
    debugArea:null,
    lastDirection:-1,
    RIGHT:0,
    LEFT:1,
    DOWN:2,
    UP:3,
    rightMinAcc:2,
    leftMinAcc:-2,
    downMinAcc:2,
    upMinAcc:1,
    rightCurAcc:null,
    leftCurAcc:null,
    downCurAcc:null,
    upCurAcc:null,
    visualRadius:3,
    init: function(canvasId){
        this.debugArea = document.querySelector('#debugArea');
        this.canvas = this.getDOM(canvasId);
        if(!this.canvas){
            console.log(canvasId+' not found');
            return;
        }
        this.canvas.style.position = 'absolute';
        this.ctx = this.canvas.getContext('2d');
        this.bufferCanvas = document.createElement('canvas');
        this.bufferCtx = this.bufferCanvas.getContext('2d');
        if(!this.ctx){
            console.log(canvasId+' is not a canvas dom');
            return;
        }
        this.resize();
        this.bindEvent();
        this.maze = new Maze(this.rowNum,this.columnNum,this.gridSize,this.gridSize);
        this.meSpirit = new Image();
        this.meSpirit.onload = function(){
            app.generateMap();
        };
        this.meSpirit.src = 'img/me.jpg';
    },
    generateMap:function(){
        this.maze.generate();
        this.map = this.maze.maze;
        this.start();
    },
    bindEvent:function(){
        document.onkeydown = function(e){
            switch(e.keyCode){
                case 37:app.moveLeft();break;
                case 38:app.moveUp();break;
                case 39:app.moveRight();break;
                case 40:app.moveDown();break;
            }
            // for(var key in e){
            //     console.log('key:'+key+',value:'+e[key]);
            // }
        }
    },
    isEmpty:function(x,y){
        return (x>0)&&(x<this.columnNum-1)&&(y>0)&&(y<this.rowNum-1)&&(this.map[y][x]==1);
    },
    moveLeft:function(){
        var row = this.pos.y;
        var col = this.pos.x;
        var direction = 2;
        var exitMask = 1 << direction;
        if ((this.map[row][col] & exitMask) != 0){
            this.pos.y = row + DROW[direction];
            this.pos.x = col + DCOL[direction];
            this.drawMap();
        }
    },
    moveRight:function(){
        // var newX = this.pos.x+1;
        // var newY = this.pos.y;
        // if(this.isEmpty(newX,newY)){
        //     this.pos.x = newX;
        //     this.pos.y = newY;
        //     this.drawMap();
        // }
        var row = this.pos.y;
        var col = this.pos.x;
        var direction = 0;
        var exitMask = 1 << direction;
        if ((this.map[row][col] & exitMask) != 0){
            this.pos.y = row + DROW[direction];
            this.pos.x = col + DCOL[direction];
            this.drawMap();
        }
    },
    moveUp:function(){
        var row = this.pos.y;
        var col = this.pos.x;
        var direction = 1;
        var exitMask = 1 << direction;
        if ((this.map[row][col] & exitMask) != 0){
            this.pos.y = row + DROW[direction];
            this.pos.x = col + DCOL[direction];
            this.drawMap();
        }
    },
    moveDown:function(){
        var row = this.pos.y;
        var col = this.pos.x;
        var direction = 3;
        var exitMask = 1 << direction;
        if ((this.map[row][col] & exitMask) != 0){
            this.pos.y = row + DROW[direction];
            this.pos.x = col + DCOL[direction];
            this.drawMap();
        }
    },
    drawMap:function(){
        this.bufferCtx.fillStyle = '#fff';
        this.bufferCtx.fillRect(0,0,this.canvas.width,this.canvas.height);
        this.maze.render(this.bufferCtx);
        this.bufferCtx.fillStyle = '#555';
        var ch = this.canvas.height;
        var cw = this.canvas.width;
        var more = 0.5*this.gridSize;
        var leftBoundary = Math.max(0,this.pos.x-this.visualRadius)*this.gridSize-more;
        this.bufferCtx.fillRect(0,0,leftBoundary,ch);

        var topBoundary = Math.max(0,this.pos.y-this.visualRadius)*this.gridSize-more;
        this.bufferCtx.fillRect(leftBoundary,0,cw-leftBoundary,topBoundary);

        var bottomBoundary = Math.min(this.rowNum,this.pos.y+this.visualRadius)*this.gridSize+more;
        this.bufferCtx.fillRect(leftBoundary,bottomBoundary,cw-leftBoundary,ch-bottomBoundary);

        var rightBoundary = Math.min(this.columnNum,this.pos.x+this.visualRadius)*this.gridSize+more;
        this.bufferCtx.fillRect(rightBoundary,topBoundary,cw-leftBoundary,bottomBoundary-topBoundary);

        this.bufferCtx.drawImage(this.meSpirit,this.pos.x*this.gridSize+2,this.pos.y*this.gridSize+2,this.gridSize-4,this.gridSize-4);
        this.ctx.drawImage(this.bufferCanvas,0,0);
        if(this.pos.x == this.columnNum-1&&this.pos.y == this.rowNum-1){
            alert('恭喜通关!');
            this.generateMap();
            return;
        }
    },
    start:function(){
        this.pos.x = 0;
        this.pos.y = 0;
        this.drawMap();
        // var options = { frequency: 1000/this.fps};
        // this.watchID = navigator.accelerometer.watchAcceleration(function(a){
        //     app.onAcceleration(a)
        // }, function(){
        //     alert('watchAcceleration error');
        // }, options);
    },
    debug:function(str){
        this.debugArea.innerHTML = str;
    },
    onAcceleration:function(acceleration){
        this.drawMap();
        var ax = acceleration.y;
        var ay = acceleration.x;
        var maxAcc = 9.5;
        switch(this.lastDirection){
            case this.RIGHT:
            this.rightCurAcc = Math.min(this.rightCurAcc+0.5,maxAcc);
            this.leftCurAcc = Math.min(this.leftCurAcc+0.5,this.leftMinAcc);
            this.upCurAcc = this.upMinAcc;
            this.downCurAcc = this.downMinAcc;
            break;
            case this.LEFT:
            this.rightCurAcc = Math.max(this.rightCurAcc-0.5,this.rightMinAcc);
            this.leftCurAcc = Math.max(this.leftCurAcc-0.5,-maxAcc);
            this.upCurAcc = this.upMinAcc;
            this.downCurAcc = this.downMinAcc;
            break;
            case this.DOWN:
            this.rightCurAcc = this.rightMinAcc;
            this.leftCurAcc = this.leftMinAcc;
            this.upCurAcc = Math.min(this.upCurAcc+0.5,this.upMinAcc);
            this.downCurAcc = Math.min(this.downCurAcc+0.5,maxAcc);
            break;
            case this.UP:
            this.rightCurAcc = this.rightMinAcc;
            this.leftCurAcc = this.leftMinAcc;
            this.upCurAcc = Math.max(this.upCurAcc-0.5,-maxAcc);
            this.downCurAcc = Math.max(this.downCurAcc-0.5,this.downMinAcc);
            break;
            default:
            this.rightCurAcc = this.rightMinAcc;
            this.leftCurAcc = this.leftMinAcc;
            this.downCurAcc = this.downMinAcc;
            this.upCurAcc = this.upMinAcc;
            break;
        }
        var newX = this.pos.x;
        var newY = this.pos.y;
        if(ax > this.rightCurAcc){
            newX++;
            this.lastDirection = this.RIGHT;
        }
        else if(ax < this.leftCurAcc){
            newX--;
            this.lastDirection = this.LEFT;
        }
        else if(ay > this.downCurAcc){
            newY++;
            this.lastDirection = this.DOWN;
        }
        else if(ay < this.upCurAcc){
            newY--;
            this.lastDirection = this.UP;
        }
        else{
            this.lastDirection = -1;
        }
        if(newX>0&&newX<this.columnNum-1&&newY>0&&newY<this.rowNum-1&&this.map[newY][newX]==1){
            this.pos.x = newX;
            this.pos.y = newY;
        }
    },
    resize:function(){
        this.width = window.innerWidth;
        this.height = window.innerHeight;
        document.body.style.width = this.width+'px';
        document.body.style.height = this.height+'px';
        this.gridSize = Math.min(this.width/this.columnNum,this.height/this.rowNum);
        this.bufferCanvas.width = this.canvas.width = this.gridSize*this.columnNum;
        this.bufferCanvas.height = this.canvas.height = this.gridSize*this.rowNum;
        this.canvas.style.width = this.canvas.width+'px';
        this.canvas.style.height = this.canvas.height+'px';
        var toTop = (this.height-this.canvas.height)/2+'px';
        var toLeft = (this.width-this.canvas.width)/2+'px';
        this.canvas.style.left = toLeft;
        this.canvas.style.top = toTop;
    },
    getDOM:function(id){
        return document.querySelector('#'+id);
    }
};
